<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
import { pageitemApi } from '@T2/service/api.ts';
import { debounce } from '@T2/utils/utils.ts';
import { getOptions, } from './utils/options.js';
import { exchangeFnc, } from './utils/exchange.js';
import vueECharts from 'vue-echarts';
import EZUIKitJs from './components/ezuikitJs.vue';
import GifDiv from './components/gifDiv.vue';
import LineCharts01 from './components/lineCharts01.vue';
import SetPLCPopup from './components/setPLCPopup.vue';
import NumberCharts from './components/numberCharts.vue';

const props = defineProps({
  dftPage: {
    type: Number,
    required: true,
  },
  showFunc: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: true,
  },
  reload: {
    type: Number,
    default: 0,
  }
});
const emits = defineEmits(['setPageID', 'setPopupID', 'setVisible', 'setPageFnc', 'setPagePrefix', 'setPageTitle']);
const option = reactive(getOptions());
const cfg = reactive({
  page: props.dftPage,
  globalReset: true,
  global: {
    editType: 'globalNormal',
    bgImgUsed: false,
    // backgroundColor: 'rgba(0, 61, 81, 1)',
    backgroundColor: 'transparent',
    bgImg: '',
    dftRender: '自适应', //'自适应，铺满'
    xAxisMax: 1920,
    yAxisMax: 1080,
  },
});
emits('setPageID', cfg.page);
watch(() => props.dftPage, (nv, ov) => {
  if (nv) {
    cfg.page = nv
  }
});
let staticPageitem = null;
onMounted(() => {
  getPageItem();
});
const getPageItem = () => {
  pageitemApi({
    method: 'get',
    params: {
      page: 1,
      ordering: '-create_time',
      page_id: cfg.page || props.dftPage,
    },
  }).then(res => {
    staticPageitem = res.results;
    if (cfg.globalReset) {
      let gitem = staticPageitem.find(i => i.item_type === 'globalNormal');
      if (gitem) {
        setDftBox(gitem);
        initRealBox();
        nextTick(() => {
          scaleRealToCover();
        });
        cfg.globalReset = false;
      }
    }
    initPageitem();
  });
}

/* 初始容器、初始显示区域 */
const zBoxRef = ref(null);
const dftBox = reactive({
  width: 1,
  height: 1,
  scale: 1,
});
const setDftBox = (gitem) => {
  let front = JSON.parse(gitem.front_data);
  cfg.global = {
    editType: 'globalNormal',
    bgImgUsed: false,
    // backgroundColor: 'rgba(0, 61, 81, 1)',
    backgroundColor: 'transparent',
    bgImg: '',
    dftRender: '自适应',
    xAxisMax: 1920,
    yAxisMax: 1080,
  };
  for (let i in front) {
    cfg.global[i] = front[i];
  }
  option.xAxis.max = cfg.global.xAxisMax;
  option.yAxis.max = cfg.global.yAxisMax;

  let
    cw = zBoxRef.value.clientWidth,
    ch = zBoxRef.value.clientHeight,
    ratio = cw / ch,
    gblRatio = cfg.global.xAxisMax / cfg.global.yAxisMax;
  if (cfg.global.dftRender === '自适应') {
    if (ratio >= gblRatio) {
      dftBox.width = ch * gblRatio;
      dftBox.height = ch;
      dftBox.scale = ch / cfg.global.yAxisMax;
    } else if (ratio < gblRatio) {
      dftBox.width = cw;
      dftBox.height = cw / gblRatio;
      dftBox.scale = cw / cfg.global.xAxisMax;
    }
  } else if (cfg.global.dftRender === '铺满') {
    if (ratio <= gblRatio) {
      dftBox.width = ch * gblRatio;
      dftBox.height = ch;
      dftBox.scale = ch / cfg.global.yAxisMax;
    } else if (ratio > gblRatio) {
      dftBox.width = cw;
      dftBox.height = cw / gblRatio;
      dftBox.scale = cw / cfg.global.xAxisMax;
    }
  }
}

/* 是否要缩放至全屏 */
const scaleMax = 1.2;
const boxScaleRt = reactive({
  value: '',
  able: false,
});
const scaleRealToCover = () => {
  const scaleX = zBoxRef.value.offsetWidth / realBoxRef.value.offsetWidth;
  const scaleY = zBoxRef.value.offsetHeight / realBoxRef.value.offsetHeight;
  if (Math.max(scaleX, scaleY) > scaleMax) {
    boxScaleRt.value = '';
    boxScaleRt.able = true;
  } else {
    boxScaleRt.value = `scale(${scaleX}, ${scaleY})`;
    boxScaleRt.able = false;
  }
  realBoxRef.value.style.transform = `translateX(0px) translateY(0px) ${boxScaleRt.value}`;
}

/* 计算缩放 */
const realBoxRef = ref(null);
const realBox = reactive({
  width: 1,
  height: 1,
  scale: 1,
});
const initRealBox = () => {
  realBox.width = dftBox.width;
  realBox.height = dftBox.height;
  realBox.scale = dftBox.scale;
}
let scroll = {
  times: 1,
  down: false,
  enter: false,
  scale: 1,
  moveEndX: 0,
  moveEndY: 0,
};
onMounted(() => {
  /* 禁用放大 */
  realBoxRef.value.onwheel = function (e) {
    if (scroll.enter && boxScaleRt.able) {
      e.preventDefault();
      scroll.times = e.zrDelta > 0 ? 1.1 : 0.9;
      calcFnc(e.offsetX, e.offsetY);
    }
  };
});
const calcFnc = (offsetX, offsetY) => {
  const temp = scroll.scale * scroll.times;
  if (temp < 4 && temp >= 1) {
    // const cdX = offsetX - (realBox.width / 2), cdY = (realBox.height / 2) - offsetY;
    // const nextCdX = cdX * scroll.times, nextCdY = cdY * scroll.times;
    // const moveX = nextCdX - cdX, moveY = nextCdY - cdY;
    // scroll.moveEndX += moveX;
    // scroll.moveEndY += moveY;
    scroll.moveEndX += (offsetX - (realBox.width / 2)) * (scroll.times - 1);
    scroll.moveEndY += ((realBox.height / 2) - offsetY) * (scroll.times - 1);
    realBoxRef.value.style.transform = `translateX(${- scroll.moveEndX}px) translateY(${scroll.moveEndY}px) ${boxScaleRt.value}`;

    scroll.scale = temp;
    realBox.width = dftBox.width * temp;
    realBox.height = dftBox.height * temp;
    realBox.scale = dftBox.scale * temp;
    initPageitem();
  }
}
const realMousedown = (e) => {
  if (boxScaleRt.able) {
    scroll.down = true;
  }
}
const realMousemove = (e) => {
  if (boxScaleRt.able && scroll.down) {
    scroll.moveEndX -= e.movementX;
    scroll.moveEndY += e.movementY;
    realBoxRef.value.style.transform = `translateX(${- scroll.moveEndX}px) translateY(${scroll.moveEndY}px) ${boxScaleRt.value}`;
  }
}

/* 页面切换 */
watch(() => cfg.page, (nv, ov) => {
  resetPageSize();
  emits('setPageID', nv);
});
const resetPageSize = () => {
  cfg.globalReset = true;
  scroll.scale = 1;
  scroll.moveEndX = 0;
  scroll.moveEndY = 0;
  realBoxRef.value.style.transform = `translateX(0px) translateY(0px) ${boxScaleRt.value}`;
  getPageItem();
}

/* 全屏、退出全屏 */
const isFullScreen = ref(false);
onMounted(() => {
  window.onresize = debounce(fullFnc, 500);
});
watch(() => props.reload, (nv, ov) => {
  if (nv) {
    fullFnc()
  }
});
const fullFnc = () => {
  if (document.fullscreenElement || document.mozFullScreenElement || document.msFullScreenElement || document.webkitFullScreenElement || document.oFullScreenElement) {
    isFullScreen.value = true;
  } else {
    isFullScreen.value = false;
  }
  cfg.globalReset = true;
  otherZList.charts = [];
  getPageItem();
}
onBeforeUnmount(() => {
  window.onresize = null;
});
const fullScreen = () => {
  if (zBoxRef.value.requestFullscreen) {
    zBoxRef.value.requestFullscreen();
  } else if (zBoxRef.value.mozRequestFullScreen) {
    zBoxRef.value.mozRequestFullScreen();
  } else if (zBoxRef.value.webkitRequestFullScreen) {
    zBoxRef.value.webkitRequestFullScreen();
  } else if (zBoxRef.value.msRequestFullscreen) {
    zBoxRef.value.msRequestFullscreen();
  } else if (zBoxRef.value.oRequestFullscreen) {
    zBoxRef.value.oRequestFullscreen();
  }
}
const exitFullScreen = () => {
  if (document.exitFullscreen) {
    document.exitFullscreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.webkitCancelFullScreen) {
    document.webkitCancelFullScreen();
  } else if (document.msCancelFullScreen) {
    document.msCancelFullScreen();
  } else if (document.oCancelFullScreen) {
    document.oCancelFullScreen();
  }
}

/* 定时刷新 */
let regularRefresh = setInterval(() => {
  getPageItem();
}, 15000);
onBeforeUnmount(() => {
  clearInterval(regularRefresh);
  regularRefresh = null;
});

/* 渲染 */
const chartRef = ref(null);
const otherZList = reactive({
  gif: [],
  charts: [],
});
let pipeline = {
  speed: {},
  timerList: [],
};
const initPageitem = () => {
  option.series = [];
  otherZList.gif = [];

  pipeline.speed = {};
  pipeline.timerList.forEach(i => clearInterval(i));
  pipeline.timerList = [];
  let seriesArr = [];
  let pipeline01Arr = []; //准备交换流动的放在后面
  let chartsArr = [];
  staticPageitem.forEach((item, index) => {
    let type = item.item_type;
    if (['text01', 'number01', 'shape01', 'bar01', 'line01', 'vButton01', 'switch01', 'gauge01'].includes(type)) {
    	let series = exchangeFnc(item, realBox.scale, '切换页面');
      if (!series) {
        return;
      }
      seriesArr.push(series);
    } else if (['picture01'].includes(type)) {
      let series = exchangeFnc(item, realBox.scale, '切换页面');
      if (!series) {
        return;
      }
      let { symbol, symbolRotate, symbolSize, value, pageT } = series.data[0];
      let arr1 = symbol.split('.gif'), arr2 = symbol.split('.GIF');
      if ((arr1.length === 2 && !arr1[1]) || (arr2.length === 2 && !arr2[1])) {
        if (series.data[0].itemStyle.opacity) {
          otherZList.gif.push({
            id_temp: item.id,
            value,
            symbol: {
              url: symbol.split('image://')[1],
              rotate: symbolRotate,
              width: symbolSize[0],
              height: symbolSize[1],
            },
            pageT: pageT,
          });
        }
      } else {
      	seriesArr.push(series);
      }
    } else if (['pipeline01'].includes(type)) {
      let series = exchangeFnc(item, realBox.scale, '切换页面');
      if (!series) {
        return;
      }
      seriesArr.push(series);
      if (series.data[0]?.statusT?.speed) {
        pipeline01Arr.push({isActive: true, index: seriesArr.length - 1});
      } else {
        pipeline01Arr.push({isActive: false, index: seriesArr.length - 1});
      }
    } else if (['lineCharts01'].includes(type)) {
      let series = exchangeFnc(item, realBox.scale, '切换页面');
      if (!series) {
        return;
      }
    	series.id_temp = item.id;
      chartsArr.push(series);
    }
  });
  for (let i = pipeline01Arr.length - 2; i >= 0; i --) {
    let obji = pipeline01Arr[i];
    if (obji.isActive) {
      for (let j = pipeline01Arr.length - 1; j > i; j --) {
        let objj = pipeline01Arr[j];
        if (!objj.isActive) {
          objj.isActive = true;
          obji.isActive = false;
          [ seriesArr[objj.index], seriesArr[obji.index] ] = [ seriesArr[obji.index], seriesArr[objj.index] ];
          break;
        }
      }
    }
  }
  seriesArr.forEach((series, index) => {
    let type = series.editType;
    if (['text01', 'number01', 'shape01', 'bar01', 'line01', 'vButton01', 'switch01', 'gauge01'].includes(type)) {
    	option.series.push(series);
    } else if (['picture01'].includes(type)) {
    	option.series.push(series);
    } else if (type === 'pipeline01') {
    	option.series.push(series);
    	if (series.data[0]?.statusT?.speed) {
    		let { speed, moveTime } = series.data[0].statusT;
    		if (!pipeline.speed[moveTime]) {
    			pipeline.speed[moveTime] = [];
    		}
    		pipeline.speed[moveTime].push([option.series.length - 1, speed]);
    	}
    }
  });
  for (const item in pipeline.speed) {
    let timer = setInterval(function () {
      pipeline.speed[item].forEach(arr => option.series[arr[0]].data[2].lineStyle.dashOffset -= arr[1]);
    }, +item);
    pipeline.timerList.push(timer);
  }
  if (chartRef.value.chart) {
    // chartRef.value.chart.clear();会闪
    chartRef.value.chart.setOption(option, true);
  }
  if (!otherZList.charts.length) {
    otherZList.charts = chartsArr;
  }
}
onBeforeUnmount(() => {
  pipeline.timerList.forEach(i => clearInterval(i));
  pipeline.timerList = [];
});

const SetPLCRef = ref(null);
const Resd = reactive({
  vButShow: false,
  vButNums: 0,
});
const vueEChartsClick = async (event) => {
  let editObj = option.series[event.seriesIndex];
  let dataIndex = event.dataIndex;
  
  if (['text01', 'picture01'].includes(editObj.editType)) {
    let pageT = editObj.data[dataIndex].pageT;
    if (pageT) {
      pageTClick(pageT);
    }
  } else if (editObj.editType === 'vButton01') {
    Resd.vButShow = true;
    Resd.vButNums += 1;
  } else if (editObj.editType === 'number01') {
    if (editObj.data[dataIndex]?.statusT?.rw === '读写') {
      SetPLCRef.value.checkPopup(editObj, dataIndex);
    } else {
      showNumberCharts(editObj);
    }
  } else if (editObj.editType === 'switch01') {
    SetPLCRef.value.checkPopup(editObj, dataIndex);
  }
}
const pageTClick = (pageT) => {
  emits('setPageFnc', pageT.fnc);
  emits('setPagePrefix', pageT.prefix);
  emits('setPageTitle', pageT.title);
  if (pageT.fnc === '切换页面') {
    cfg.page = pageT.page;
  } else if (pageT.fnc === '弹出画面' || pageT.fnc === '公共弹窗') {
    emits('setPopupID', pageT.page);
    emits('setVisible', true);
  }
}

const NumberPopResd = reactive({
  visible: false,
  editObj: {},
});
const showNumberCharts = (editObj) => {
  NumberPopResd.editObj = editObj;
  NumberPopResd.visible = true;
}
const closeNumberCharts = () => {
  NumberPopResd.visible = false;
  NumberPopResd.editObj = {};
}
</script>

<template>
  <div ref="zBoxRef" class="zutaiBox flex-center-center" :style="{ background: cfg.global.backgroundColor }">
    <div class="funcBut flex-end-center" v-if="props.showFunc">
      <el-button link @click="resetPageSize();">还原</el-button>
      |
      <el-button link :class="{ 'isActive': isFullScreen }" @click="fullScreen();">全屏</el-button>
      <el-button link :class="{ 'isActive': !isFullScreen }" @click="exitFullScreen();">窗口</el-button>
      <span class="arrow"></span>
    </div>

    <div
      ref="realBoxRef"
      class="box_canvas"
      :style="{
        width: realBox.width + 'px',
        height: realBox.height + 'px',
        minWidth: realBox.width + 'px',
        minHeight: realBox.height + 'px',
      }"
      @mousedown="realMousedown"
      @mousemove="realMousemove"
      @mouseup="scroll.down = false"
      @mouseleave="scroll.down = false"
      @mouseenter="scroll.enter = true"
    >
      <div class="backColor">
        <img :src="cfg.global.bgImg" v-if="cfg.global.bgImgUsed" />
      </div>

      <vueECharts ref="chartRef" autoresize :option="option" @click="vueEChartsClick"></vueECharts>

      <GifDiv
        v-for="(item, index) in otherZList.gif"
        :key="item.id_temp"
        :realBox="realBox"
        :position="item.value"
        :symbol="item.symbol"
        :pageT="item.pageT"
        @mouseenter="scroll.enter = false"
        @mouseleave="scroll.enter = true"
        @setPopup="(pageT) => {pageTClick(pageT)}"
      />

      <LineCharts01
        v-for="(item, index) in otherZList.charts"
        :key="item.id_temp"
        :realBox="realBox"
        :position="item.data[0].value"
        :label="item.data[0].label"
        :option="item.option"
        :params="item.params"
        @mouseenter="scroll.enter = false"
        @mouseleave="scroll.enter = true"
      />
      
      <el-dialog
        v-model="Resd.vButShow"
        :show-close="false"
        :destroy-on-close="true"
        :center="true"
        :draggable="true"
        width="fit-content"
      >
        <EZUIKitJs :vid="'vid' + Resd.vButNums" v-if="Resd.vButShow"></EZUIKitJs>
      </el-dialog>
    </div>
  </div>

  <SetPLCPopup ref="SetPLCRef" :disabled="props.disabled" />
  
  <NumberCharts
    v-if="NumberPopResd.visible"
    :editObj="NumberPopResd.editObj"
    @close="closeNumberCharts"
  />
</template>

<style lang="scss" scoped>
.zutaiBox {
  width: inherit;
  height: 100%;
  background-color: #003D51;
  position: relative;
  overflow: hidden;
}
.funcBut {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 999;
  height: 30px;
  background-color: #00799a;
  width: 15px;
  overflow: hidden;
  border-radius: 0 20px 20px 0;
  transition: width .5s;
  cursor: pointer;
  .arrow {
    min-width: 20px;
    text-align: center;
    color: #fff;
    &::after {
      content: '>';
    }
  }
  button {
    color: #fff;
    padding: 4px 5px;
    margin: 0;
    :hover {
      opacity: .8;
    }
    &.isActive {
      color: rgba(0, 255, 255, 1);
    }
  }
  &:hover {
    width: 150px;
    .arrow::after {
      content: '';
    }
  }
}
.box_canvas {
  position: relative;

  .backColor {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;

    img {
      width: 100%;
      height: 100%;
    }
  }

  .gifC {
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
    left: 20px;
  }
  
  :deep(.el-dialog) {
    padding: 0;
    header {
      display: none;
    }
  }
}

</style>
